#pragma once

#include "giovanni.peroni.h"
//#include "../common/basetypes.h"
#include "../common/MathUtils.h"
#include "math.h"


bool GiovanniPeroni::Init(Register& o_register)
{
	m_name = "GIOVANNI PERONI";

	REGISTER_FUNC(GiovanniPeroni, 1);
	REGISTER_FUNC(GiovanniPeroni, 2);
	REGISTER_FUNC(GiovanniPeroni, 3);
	REGISTER_FUNC(GiovanniPeroni, 4);

	return true;
}

RetType GiovanniPeroni::Problem1()
{
	// Add all the natural numbers below one thousand that are
	// multiples of 3 or 5.
	RetType sum = 0;
	UInt counter = 1;
	while (counter < 1000)
	{
		if ((counter % 3 == 0) || (counter % 5 == 0))
			sum += counter;
		++counter;
	}
	//cout << "The result is: " << sum;
	//system("pause");
	return sum;
}

RetType GiovanniPeroni::Problem2()
{
	// Find the sum of all the even-valued terms in the
	// Fibonacci sequence which do not exceed four million.
	RetType sum = 0;
	UInt curNum = 1;
	UInt prevNum = 0;
	while (curNum < 4000000)
	{
		if (curNum % 2 == 0)
			sum += curNum;
		curNum += prevNum;
		prevNum = curNum - prevNum;
	}
	return sum;
}

RetType largestFactor (const RetType num)
{
	/* Returns the largest factor of 'num' by dividing it
	by its minimum factor. If 'num' is prime, returns 'num'. */
	for (int i = 2; i < num; ++i)
	{
		if (num % i == 0)
			return (num / i);
	}
	return num;
}

RetType GiovanniPeroni::Problem3()
{
	// What is the largest prime factor of the number 600851475143 ?

	/* Ok, this could be a bit tricky, and actually I'm not sure it's correct.
	I tried it with other numbers and it seems to work fine; it's also
	quite fast, unless 'number' is the largest prime factor of itself (worst case).
	
	If you divide 'number' by its minimum factor (i.e. 2 if 'number' is even),
	you get its largest factor. This is what the function 'largestFactor' does.
	Then you call largestFactor again and again, each time passing as argument
	the largest	factor of the previous number, until you get that the largest
	factor is the argument itself. In this case, the argument is prime, and
	it's the largest prime factor of the original number as well.
	
	Do you guys think this is correct?
	*/

	RetType number = 600851475143;
	while (number != largestFactor(number))
	{
		number = largestFactor(number);
	}
	return number;
}

RetType GiovanniPeroni::Problem4()
{
	// Find the largest palindrome made from the product of two 3-digit numbers.
	UInt32 product = 0;
	for (int i = 999; i > 99; --i)
	{
		for (int k = 999; k > 99; --k)
		{
			if ((k*i > product) && math::IsPalindrome(k*i))
				product = k*i;
		}
	}
	return product;
}


